﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "StructureFloor.h"
#include "AlgorithmCurveOperate.h"
#include "DbObjectUtils.h"
#include "GbmpBuiltInParameterDefinitionsNew.h"
#include "GbmpBuiltInParameterStaticVauleListItems.h"
#include "GcmpBuiltInParameterDefinitions.h"
#include "GmIStructureFactory.h"
#include "ICalculator.h"
#include "ICalculatorCollection.h"
#include "ICopyStrategyReporter.h"
#include "IDocument.h"
#include "IElement.h"
#include "IElementParameters.h"
#include "IElementParentReporter.h"
#include "IElementPosition.h"
#include "IElementStatus.h"
#include "IElementTransformationComponent.h"
#include "IExternalDataComponent.h"
#include "IFamily.h"
#include "IGenericElement.h"
#include "IGraphicsCurve3d.h"
#include "IInstance.h"
#include "IInstanceType.h"
#include "ILevel.h"
#include "ILine3d.h"
#include "IModelLine.h"
#include "IParameter.h"
#include "IParameterDefinitionLibrary.h"
#include "IPositionAssociatedPlane.h"
#include "IPositionPoint2d.h"
#include "IRegenerator.h"
#include "IRegeneratorDataIdCreator.h"
#include "IStructureSlopeLine.h"
#include "InstancePlacementTypes.h"
#include "LevelUtils.h"
#include "ProfileUsedModelLineUtils.h"
#include "StructureFloorGraphicsElementShapeBehavior.h"
#include "StructureInstanceCutterGRepComponent.h"
#include "StructureInstanceInput.h"
#include "StructureInstanceLevelUtils.h"
#include "StructureProfileInstanceInput.h"
#include "StructureProfileInstanceUtils.h"
#include "IGeometryRelationshipComponent.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"


using namespace gcmp;

IMPLEMENT_REGEN_FUNCTIONS(gcmp, StructureFloor, SlopeLineId);
IMPLEMENT_REGEN_FUNCTIONS(gcmp, StructureFloor, Volume)
IMPLEMENT_REGEN_FUNCTIONS(gcmp, StructureFloor, Area)
IMPLEMENT_REGEN_FUNCTIONS(gcmp, StructureFloor, TopElevation)
IMPLEMENT_REGEN_FUNCTIONS(gcmp, StructureFloor, BottomElevation)
IMPLEMENT_REGEN_FUNCTIONS(gcmp, StructureFloor, SlopeAngle)
IMPLEMENT_REGEN_FUNCTIONS(gcmp, StructureFloor, SlopeStartHeight)
IMPLEMENT_REGEN_FUNCTIONS(gcmp, StructureFloor, SlopeEndHeight)

DEFINE_STRUCTURE_INSTANCE_METHODS(StructureFloor);

DBOBJECT_DATA_DEFINE(StructureFloor)
{
    m_pOwnerElement = nullptr;
    SetSlopeLineId__(ElementId::InvalidID);
    SetVolume__(0);
    SetArea__(0);
    SetTopElevation__(0);
    SetBottomElevation__(0);
    SetSlopeAngle__(0);
    SetSlopeStartHeight__(0);
    SetSlopeEndHeight__(0);
    SetConcreteStrengthGrade__(ConcreteStrengthGradeType::CSG_C30);
}

gcmp::StructureFloor* StructureFloor::Create(const StructureProfileInstanceGeometryInput* pInput)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInput, L"pInput为空",L"GDMPLab",L"2024-03-30");

    IDocument* pDoc = pInput->Document;
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    const IPolygon* pPolygon = pInput->ProfilePolygon.get();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pPolygon, L"pPolygon为空",L"GDMPLab",L"2024-03-30");

    ElementId associatedPlaneId = pInput->AssociatedPlaneId;
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(associatedPlaneId.IsValid(), L"associatedPlaneId无效",L"GDMPLab",L"2024-03-30");

    OwnerPtr<StructureProfileInstanceElementInput> pElementInput = NEW_AS_OWNER_PTR(StructureProfileInstanceElementInput);

    std::vector<IModelLine*> profileCurves;
    bool bOk = StructureProfileInstanceUtils::GenerateProfileCurvesFromPolygon(pDoc, pPolygon, associatedPlaneId, profileCurves);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"ProfileCurves生成失败",L"GDMPLab",L"2024-03-30");

    // 构造一个StructureSlopeLine
    const StructureFloorSlopeLineInput* pSlopeLineInput = pInput->FloorSlopeLine.get();
    IStructureSlopeLine* pSlopeLine = nullptr;
    if(pSlopeLineInput)
    {
        pSlopeLine = StructureProfileInstanceUtils::GenerateStructureFloorSlopeLine(pDoc, pSlopeLineInput);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pSlopeLine, L"SlopeLine生成失败",L"GDMPLab",L"2024-03-30");
    }

    // 继承自StructureInstanceInput的参数
    pElementInput->Document = pDoc;
    pElementInput->AssociatedPlaneId = associatedPlaneId;
    pElementInput->StoreyId = pInput->StoreyId;
    pElementInput->FamilyId = pInput->FamilyId;
    pElementInput->InstanceTypeId = pInput->InstanceTypeId;
    pElementInput->CreationOption = pInput->CreationOption;
    pElementInput->CanBeShared = pInput->CanBeShared;
    pElementInput->Visible = pInput->Visible;
    // 继承自StructureProfileInstanceGeometryInput的参数
    pElementInput->ProfileCurves = profileCurves;
    pElementInput->FloorSlopeLine = pSlopeLine;
    pElementInput->AssociatedPlaneId = pInput->AssociatedPlaneId;
    pElementInput->ConcreteType = pInput->ConcreteType;
    pElementInput->AssociatedPlaneOffset = pInput->AssociatedPlaneOffset;

    // 调用API创建楼板
    StructureFloor* pFloor = StructureFloor::Create(pElementInput.get());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pFloor, L"pFloor为空",L"GDMPLab",L"2024-03-30");

    return pFloor;
}

gcmp::StructureFloor* StructureFloor::Create(const StructureProfileInstanceElementInput* pInput)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInput, L"pInput为空",L"GDMPLab",L"2024-03-30");

    IDocument* pDoc = pInput->Document;
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    IInstanceType* pInstanceType = quick_cast<IInstanceType>(pDoc->GetElement(pInput->InstanceTypeId));
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInstanceType, L"pInstanceType为空",L"GDMPLab",L"2024-03-30");

    IInstance* pInstance = pInstanceType->CreateInstance(L"楼板实例", pInput->CanBeShared, pInput->CreationOption, pInput->IsCreateGeometryRelationshipComponent);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInstance, L"pInstance为空",L"GDMPLab",L"2024-03-30");

    IGeometryRelationshipComponent* pGeometryRepCmpt = pInstance->GetGeometryRelationshipComponent();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pGeometryRepCmpt, L"pGeometryRepCmpt不能为空",L"GDMPLab",L"2024-03-30");
    pGeometryRepCmpt->SetCutterGraphicsElementShapeComponent(NEW_AS_OWNER_PTR(StructureInstanceCutterGRepComponent));

    IElementStatus* pStatus = pInstance->GetStatus();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pStatus, L"无法获取状态集",L"GDMPLab",L"2024-03-30");
    pStatus->SetIsVisible(pInput->Visible);

    //设置实例外部自定义数据
    StructureFloor* pFloor = StructureFloor::RegisterExternalData(pInstance);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pFloor, L"pFloor为空",L"GDMPLab",L"2024-03-30");
    pFloor->SetConcreteStrengthGrade(pInput->ConcreteType);
    //模型线
    std::vector<IModelLine*> profileCurves = pInput->ProfileCurves;
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(!profileCurves.empty(), L"profileCurves为空",L"GDMPLab",L"2024-03-30");
    //坡度线
    IStructureSlopeLine* pSlopeLine = pInput->FloorSlopeLine;
    //更新Instance
    bool bOk = pFloor->UpdateFloorProfilesAndSlopeLine(profileCurves, pSlopeLine);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"更新Instance无效",L"GDMPLab",L"2024-03-30");

    std::vector<OwnerPtr<ICurve3d>> profileICurvesOwner;
    std::vector<const ICurve3d*> profileICurves;
    std::vector<OwnerPtr<ICurve3d>> outerCurves; // 外圈轮廓
    std::vector<int> outerIndexes;
    for(auto& pModelLine : profileCurves)
    {
        OwnerPtr<ICurve3d> opCurve3d = pModelLine->GetGeometryCurve();
        profileICurves.push_back(opCurve3d.get());
        profileICurvesOwner.push_back(TransferOwnership(opCurve3d));
    }
    gcmp::AlgorithmCurveOperate::CreateSequencedCurves(profileICurves, outerCurves, outerIndexes);

    // 计算一个插值点
    Vector3d insertPt = Vector3d::Zero;
    {
        std::vector<const ICurve3d*> curves;
        FOR_EACH(curve, outerCurves)
        {
            curves.push_back(curve.get());
        }

        Box3d box;
        FOR_EACH(pCurve, curves)
        {
            box.MergeBox(pCurve->GetBox());
        }

        insertPt = box.GetCenter();
    }

    ElementId topLevelId = pInput->AssociatedPlaneId;
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(topLevelId.IsValid(), L"topLevelId无效",L"GDMPLab",L"2024-03-30");

    const ILevel* pStoreyLevel = nullptr;
    if(pInput->StoreyId.IsValid())
    {
        pStoreyLevel = LevelUtils::GetLevelById(pDoc, pInput->StoreyId);
    }
    else
    {
        pStoreyLevel = StructureInstanceLevelUtils::GetFloorStoreyLevelFromPositioningLevel(pDoc, topLevelId);
    }
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pStoreyLevel, L"pStoreyLevel为空",L"GDMPLab",L"2024-03-30");

    bOk = StructureInstanceLevelUtils::CreateInstanceStoreyLevel(pInstance, pStoreyLevel);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"设置楼板的StoreyLevel失败",L"GDMPLab",L"2024-03-30");

    // 以插入点为原点坐标系
    Coordinate3d baseCoord(insertPt, Vector3d::UnitX, Vector3d::UnitY);
    OwnerPtr<IPolygon> opPolygon = StructureProfileInstanceUtils::CalculateProfilePolygon(profileICurves, baseCoord);

    bOk = IElementPosition::CreatePoint2dOnTopAssociatedPlanePositionBehavior(pInstance,
        topLevelId, baseCoord.GetOrigin(), baseCoord.GetX(), baseCoord.GetY());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"PositionBehavior创建失败",L"GDMPLab",L"2024-03-30");
    if (!IPositionAssociatedPlane::SetTopPlaneHeightOffset(pInstance, pInput->AssociatedPlaneOffset))
        IPositionAssociatedPlane::SetBottomPlaneHeightOffset(pInstance, pInput->AssociatedPlaneOffset);

    if(opPolygon)
    {
        bool bOk = StructureProfileInstanceUtils::SetProfileByCurveArray(opPolygon.get(), baseCoord, pInstance);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"更新轮廓曲线失败",L"GDMPLab",L"2024-03-30");
        const IElementParameters* pElementParameters = pInstance->GetElementParameters();
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pElementParameters, L"pElementParameters为空",L"GDMPLab",L"2024-03-30");

        int parameterValue = 0;
        bool hasParameter = pElementParameters->GetParameterValueAsInt(PARAMETER_UID(InstancePlacementTypeBuiltInParamter), parameterValue);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(hasParameter, L"placementType参数获取失败",L"GDMPLab",L"2024-03-30");

        InstancePlacementTypes placementType = (InstancePlacementTypes)parameterValue;
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(placementType == InstancePlacementTypes::FamilyBasedOnProfile, L"placementType参数获取失败",L"GDMPLab",L"2024-03-30");
    }

    //设置补偿高度，值与 AlgorithmBodyTopologyOperate::FitBodyToTargetedFaceWithoutTopoChange的延伸值一直
    StructureProfileInstanceUtils::SetFloorCompensationThickness(pInstance, (int)Constants::MAX_MODEL_SIZE / 3.0);

    ProfileUsedModelLineUtils::SetAssociatedInstanceIdForModelLines(profileCurves, pInstance->GetElementId());

    // 将模型线从世界坐标系转换到楼板的局部坐标系，这样以后就可以根据楼板PositionHelper位置更新模型线的位置。
    const IElementPosition *posBehavior = pInstance->GetElementPosition();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(posBehavior, L"posBehavior不能为空",L"GDMPLab",L"2024-03-30");

    Matrix4d mat = posBehavior->ComputeLocalToWorldCoordinateSystemTransformMatrix();
    bOk = mat.MakeInverse();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"MakeInverse失败",L"GDMPLab",L"2024-03-30");

    if(pSlopeLine && pSlopeLine->GetOwnerElement() && pSlopeLine->GetOwnerElement()->GetElementId() != ElementId::InvalidID)
    {
        pSlopeLine->SetInstanceId(pInstance->GetElementId());
        IGenericElement* pGenericElement = quick_cast<IGenericElement> (pSlopeLine->GetOwnerElement());
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pGenericElement && pGenericElement->GetElementPosition(), L"获取positionBehavior为空！",L"GDMPLab",L"2024-03-30");

        IElementPosition* pSlopeLineElement = pGenericElement->GetElementPosition();
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pSlopeLineElement, L"获取pElementPosition为空！",L"GDMPLab",L"2024-03-30");

        IPositionAssociatedPlane* pAssociatedPlane = pSlopeLineElement->GetPositionAssociatedPlane();
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pAssociatedPlane, L"获取pAssociatedPlane为空！",L"GDMPLab",L"2024-03-30");

        pAssociatedPlane->SetBasePlaneOffset(pInput->AssociatedPlaneOffset);
        pGenericElement->GetElementTransformationComponent()->Transform(mat);
        IElementStatus* pStatus = pGenericElement->GetStatus();
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pStatus, L"无法获取状态集",L"GDMPLab",L"2024-03-30");
        pStatus->SetIsVisible(false);
    }

    FOR_EACH(pModelLine, profileCurves)
    {
        pModelLine->GetOwnerElement()->GetStatus()->SetIsVisible(false);
        //设置轮廓线在基准面上的偏移
        IGenericElement* pGenericElement = quick_cast<IGenericElement> (pModelLine->GetOwnerElement());
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pGenericElement, L"获取pGenericElement为空！",L"GDMPLab",L"2024-03-30");

        IElementPosition* pModelLineElementPosition = pGenericElement->GetElementPosition();
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pModelLineElementPosition, L"获取pElementPosition为空！",L"GDMPLab",L"2024-03-30");

        IPositionAssociatedPlane* pAssociatedPlane = pModelLineElementPosition->GetPositionAssociatedPlane();
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pAssociatedPlane, L"获取pAssociatedPlane为空！",L"GDMPLab",L"2024-03-30");

        pAssociatedPlane->SetBasePlaneOffset(pInput->AssociatedPlaneOffset);
        pGenericElement->GetElementTransformationComponent()->Transform(mat);
    }

    OwnerPtr<StructureFloorGraphicsElementShapeBehavior> opGRepBehavior = NEW_AS_OWNER_PTR(StructureFloorGraphicsElementShapeBehavior, pInstance);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opGRepBehavior, L"opGRepBehavior不能为空",L"GDMPLab",L"2024-03-30");
    pInstance->AddGraphicsElementShapeCustomizableBehavior(TransferOwnership(opGRepBehavior), GuidUtils::GetInvalid());

    bool isOk = pDoc->GetRegenerator()->RegenerateElement(pInstance->GetElementId());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(isOk, L"RegenerateElement失败",L"GDMPLab",L"2024-03-30");

    return StructureFloor::Get(pInstance);
}

gcmp::StructureFloor* StructureFloor::Edit(const StructureProfileInstanceEditGeometryInput* pInput)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInput, L"pInput为空",L"GDMPLab",L"2024-03-30");

    IDocument* pDoc = pInput->Document;
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    const IPolygon* pPolygon = pInput->ProfilePolygon.get();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pPolygon, L"pPolygon为空",L"GDMPLab",L"2024-03-30");

    ElementId instanceId = pInput->InstanceId;
    IInstance* pInstance = quick_cast<IInstance>(pDoc->GetElement(instanceId));
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInstance, L"pInstance为空",L"GDMPLab",L"2024-03-30");

    const IElementPosition* posBehavior = pInstance->GetElementPosition();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(posBehavior, L"posBehavior为空",L"GDMPLab",L"2024-03-30");
    const IPositionAssociatedPlane* posAssociatedPlane = quick_cast<const IPositionAssociatedPlane>(posBehavior->GetPositionAssociatedPlane());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(posAssociatedPlane, L"posAssociatedPlane为空",L"GDMPLab",L"2024-03-30");
    ElementId associatedPlaneId = posAssociatedPlane->GetBasePlaneElementId();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(associatedPlaneId.IsValid(), L"associatedPlaneId无效",L"GDMPLab",L"2024-03-30");

    std::vector<IModelLine*> profileCurves;
    bool bOk = StructureProfileInstanceUtils::GenerateProfileCurvesFromPolygon(pDoc, pPolygon, associatedPlaneId, profileCurves);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"ProfileCurves生成失败",L"GDMPLab",L"2024-03-30");

    // 构造一个StructureSlopeLine
    const StructureFloorSlopeLineInput* pSlopeLineInput = pInput->FloorSlopeLine.get();
    IStructureSlopeLine* pSlopeLine = nullptr;
    if(pSlopeLineInput)
    {
        pSlopeLine = StructureProfileInstanceUtils::GenerateStructureFloorSlopeLine(pDoc, pSlopeLineInput);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pSlopeLine, L"SlopeLine生成失败",L"GDMPLab",L"2024-03-30");
    }

    OwnerPtr<StructureProfileInstanceEditElementInput> pElementInput = NEW_AS_OWNER_PTR(StructureProfileInstanceEditElementInput);
    pElementInput->Document = pDoc;
    pElementInput->InstanceId = instanceId;
    pElementInput->ProfileCurves = profileCurves;
    pElementInput->FloorSlopeLine = pSlopeLine;

    // 调用API编辑楼板
    StructureFloor* pFloor = StructureFloor::Edit(pElementInput.get());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pFloor, L"pFloor为空",L"GDMPLab",L"2024-03-30");

    return pFloor;
}

gcmp::StructureFloor* StructureFloor::Edit(const StructureProfileInstanceEditElementInput* pInput)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInput, L"pInput为空",L"GDMPLab",L"2024-03-30");

    IDocument* pDoc = pInput->Document;
    DBG_WARN_AND_RETURN_UNLESS(pDoc != nullptr, nullptr, L"pInstance为空",L"GDMPLab",L"2024-03-30");

    ElementId idInstance = pInput->InstanceId;
    IInstance *pInstance = quick_cast<IInstance>(pDoc->GetElement(idInstance));
    DBG_WARN_AND_RETURN_UNLESS(pInstance != nullptr, nullptr, L"pInstance为空",L"GDMPLab",L"2024-03-30");

    const IElementPosition *posBehavior = pInstance->GetElementPosition();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(posBehavior, L"posBehavior为空",L"GDMPLab",L"2024-03-30");

    const IPositionPoint2d *posPoint2d = dynamic_cast<const IPositionPoint2d*>(posBehavior->GetPositionGeometry());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(posPoint2d, L"posPoint2d为空",L"GDMPLab",L"2024-03-30");

    const IPositionAssociatedPlane *posAssociatedPlane = dynamic_cast<const IPositionAssociatedPlane*>(posBehavior->GetPositionAssociatedPlane());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(posAssociatedPlane, L"posAssociatedPlane为空",L"GDMPLab",L"2024-03-30");

    StructureFloor* pFloor = StructureFloor::Get(pInstance);
    DBG_WARN_AND_RETURN_UNLESS(pFloor, nullptr, L"获取板的externalData失败！",L"GDMPLab",L"2024-03-30");

    std::vector<IModelLine*> profileCurves = pInput->ProfileCurves;
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(!profileCurves.empty(), L"profileCurves为空",L"GDMPLab",L"2024-03-30");

    IStructureSlopeLine* pSlopeLine = pInput->FloorSlopeLine;
    //更新Instance
    bool bOk = pFloor->UpdateFloorProfilesAndSlopeLine(profileCurves, pSlopeLine);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"更新Instance无效",L"GDMPLab",L"2024-03-30");

    std::vector<OwnerPtr<ICurve3d>> profileICurvesOwner;
    std::vector<const ICurve3d*> profileICurves;
    std::vector<OwnerPtr<ICurve3d>> outerCurves; // 外圈轮廓
    std::vector<int> outerIndexes;

    for(auto& pModelLine : profileCurves)
    {
        OwnerPtr<ICurve3d> opCurve3d = pModelLine->GetGeometryCurve();
        profileICurves.push_back(opCurve3d.get());
        profileICurvesOwner.push_back(TransferOwnership(opCurve3d));
    }
    gcmp::AlgorithmCurveOperate::CreateSequencedCurves(profileICurves, outerCurves, outerIndexes);

    //设置补偿高度，值与 AlgorithmBodyTopologyOperate::FitBodyToTargetedFaceWithoutTopoChange的延伸值一直
    StructureProfileInstanceUtils::SetFloorCompensationThickness(pInstance, (int)Constants::MAX_MODEL_SIZE / 3.0);
    ProfileUsedModelLineUtils::SetAssociatedInstanceIdForModelLines(profileCurves, pInstance->GetElementId());

    StructureProfileInstanceUtils::MirrorProfileCoordinate(pInstance, profileICurvesOwner);

    // 保持原有插入点的位置
    Vector3d insertPt(posPoint2d->GetOrigin(), posAssociatedPlane->GetBasePlaneHeight());
    Coordinate3d baseCoord(insertPt, posPoint2d->GetDirectionX(), posPoint2d->GetDirectionY());
    OwnerPtr<IPolygon> opPolygon = StructureProfileInstanceUtils::CalculateProfilePolygon(profileICurves, baseCoord);

    if(!StructureProfileInstanceUtils::SetProfileByCurveArray(opPolygon.get(), baseCoord, pInstance))//这个函数baseCoor没用啊？？？
    {
        return nullptr;
    }
    //****************************************需要注意**************************************************
    // 将模型线从世界坐标系转换到楼板的局部坐标系，这样以后就可以根据楼板PositionHelper位置更新模型线的位置。
    Matrix4d mat = posBehavior->ComputeLocalToWorldCoordinateSystemTransformMatrix();
    bOk = mat.MakeInverse();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"MakeInverse失败",L"GDMPLab",L"2024-03-30");

    FOR_EACH(pModelLine, profileCurves)
    {
        pModelLine->GetOwnerElement()->GetStatus()->SetIsVisible(false);
        pModelLine->GetOwnerElement()->GetElementTransformationComponent()->Transform(mat);
    }

    if(pSlopeLine)
    {
        if(pSlopeLine->GetInstanceId() != pInstance->GetElementId())
        {
            pSlopeLine->SetInstanceId(pInstance->GetElementId());
        }
        IElement* pGenericElement = pSlopeLine->GetOwnerElement();
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pGenericElement && pGenericElement->GetElementPosition(), L"获取positionBehaviour为空！",L"GDMPLab",L"2024-03-30");
        pGenericElement->GetElementPosition()->Transform(mat);
        IElementStatus* pStatus = pGenericElement->GetStatus();
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pStatus, L"无法获取状态集",L"GDMPLab",L"2024-03-30");
        pStatus->SetIsVisible(false);
    }

    IElementStatus* pStatus = pInstance->GetStatus();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pStatus, L"无法获取状态集",L"GDMPLab",L"2024-03-30");
    pStatus->SetIsVisible(true);
    bOk = pDoc->GetRegenerator()->RegenerateElement(pInstance->GetElementId());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"RegenerateElement失败",L"GDMPLab",L"2024-03-30");
    return StructureFloor::Get(pInstance);
}

gcmp::StructureFloor* StructureFloor::Get(IInstance* pInstance)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInstance, L"pInstance为空",L"GDMPLab",L"2024-03-30");
    if (IExternalDataComponent * pExternalDataComponent = pInstance->GetExternalDataComponent())
    {
        IExternalData* pData = pExternalDataComponent->FindExternalData(StructureFloor::GetStaticClassSchema()->GetName());
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pData, L"pData为空",L"GDMPLab",L"2024-03-30");

        return quick_cast<StructureFloor>(pData);
    }
    return nullptr;
}

const gcmp::StructureFloor* StructureFloor::Get(const IInstance* pInstance)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInstance, L"pInstance为空",L"GDMPLab",L"2024-03-30");
    if (const IExternalDataComponent * pExternalDataComponent = pInstance->GetExternalDataComponent())
    {
        const IExternalData* pData = pExternalDataComponent->FindExternalData(StructureFloor::GetStaticClassSchema()->GetName());
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pData, L"pData为空",L"GDMPLab",L"2024-03-30");

        return quick_cast<const StructureFloor>(pData);
    }
    return nullptr;
}

void StructureFloor::UpdateForWeakParentDeletion(const std::set<ElementId>& deletedElementIds)
{
    FOR_EACH(id, deletedElementIds)
    {
        if(id == GetSlopeLineId__())
        {
            SetSlopeLineId__(ElementId::InvalidID);
        }
        auto it = std::find(GetProfileIdsFW__().begin(), GetProfileIdsFW__().end(), id);
        if(it != GetProfileIdsFW__().end())
        {
            GetProfileIdsFW__().erase(it);
        }
    }
}

void StructureFloor::ReportParents(IElementParentReporter& reporter) const
{
    if(GetSlopeLineId__().IsValid())
    {
        reporter.ReportWeak(GetSlopeLineId__());
    }
    FOR_EACH(id, GetProfileIds__())
    {
        reporter.ReportWeak(id);
    }
}

DECLARE_CALCULATOR_CREATOR(InstanceVolumeCalculator)
DECLARE_CALCULATOR_CREATOR(StructureFloorAreaCalculator)
DECLARE_CALCULATOR_CREATOR(StructureFloorTopElevationCalculator)
DECLARE_CALCULATOR_CREATOR(StructureFloorBottomElevationCalculator)
DECLARE_CALCULATOR_CREATOR(StructureFloorSlopeAngleCalculator)
DECLARE_CALCULATOR_CREATOR(StructureFloorSlopeStartHeightCalculator)
DECLARE_CALCULATOR_CREATOR(StructureFloorSlopeEndHeightCalculator)

void StructureFloor::GetCalculators(ICalculatorCollection * calculators) const
{
    ADD_CALCULATOR(InstanceVolumeCalculator, GetDocument(), GetVolumeRdId());
    ADD_CALCULATOR(StructureFloorAreaCalculator, GetDocument(), GetAreaRdId());
    ADD_CALCULATOR(StructureFloorTopElevationCalculator, GetDocument(), GetTopElevationRdId());
    ADD_CALCULATOR(StructureFloorBottomElevationCalculator, GetDocument(), GetBottomElevationRdId());
    ADD_CALCULATOR(StructureFloorSlopeAngleCalculator, GetDocument(), GetSlopeAngleRdId());
    ADD_CALCULATOR(StructureFloorSlopeStartHeightCalculator, GetDocument(), GetSlopeStartHeightRdId());
    ADD_CALCULATOR(StructureFloorSlopeEndHeightCalculator, GetDocument(), GetSlopeEndHeightRdId());
}

void StructureFloor::ReportParameterDefinitions(std::vector<int>* pParamDefIds) const
{
    pParamDefIds->push_back(PARAMETER_ID(AreaBuiltInParameter));
    pParamDefIds->push_back(PARAMETER_ID(VolumeBuiltInParameter));
    pParamDefIds->push_back(PARAMETER_ID(FloorSlopeAngleBuiltInParameter));
    pParamDefIds->push_back(PARAMETER_ID(TopElevationBuiltInParameter));
    pParamDefIds->push_back(PARAMETER_ID(BottomElevationBuiltInParameter));
    pParamDefIds->push_back(PARAMETER_ID(FloorSlopeStartHeightBuiltInParameter));
    pParamDefIds->push_back(PARAMETER_ID(FloorSlopeEndHeightBuiltInParameter));
    pParamDefIds->push_back(PARAMETER_ID(ConcreteStrengthGradeBuiltInParameter));
}

OwnerPtr<IParameter> StructureFloor::GetNativeParameter(int paramDefId) const
{
    OwnerPtr<IParameter> param;
    ParameterAttributes pa = {false, false, true};
    if(paramDefId == PARAMETER_ID(VolumeBuiltInParameter))
    {
        //param = NEW_AS_OWNER_PTR(Parameter, GetDocument(), ParameterStorageType::Double, false, false,
            //true, PARAMETER_UID(VolumeBuiltInParameter), ParameterProcessType::GeneralOutput);
        param = IParameter::CreateParameter(GetDocument(), ParameterStorageType::Double, pa,
            PARAMETER_UID(VolumeBuiltInParameter), ParameterProcessType::GeneralOutput);
        param->SetValueAsDouble(GetVolume());
        return TransferOwnership(param);
    }
    else if(paramDefId == PARAMETER_ID(AreaBuiltInParameter))
    {
        //param = NEW_AS_OWNER_PTR(Parameter, GetDocument(), ParameterStorageType::Double, false, false,
            //true, PARAMETER_UID(AreaBuiltInParameter), ParameterProcessType::GeneralOutput);
        param = IParameter::CreateParameter(GetDocument(), ParameterStorageType::Double, pa, 
            PARAMETER_UID(AreaBuiltInParameter), ParameterProcessType::GeneralOutput);
        param->SetValueAsDouble(GetArea());
        return TransferOwnership(param);
    }
    else if(paramDefId == PARAMETER_ID(TopElevationBuiltInParameter))
    {
        //param = NEW_AS_OWNER_PTR(Parameter, GetDocument(), ParameterStorageType::Double, false, false,
            //true, PARAMETER_UID(TopElevationBuiltInParameter), ParameterProcessType::GeneralOutput);
        param = IParameter::CreateParameter(GetDocument(), ParameterStorageType::Double, pa,
            PARAMETER_UID(TopElevationBuiltInParameter), ParameterProcessType::GeneralOutput);
        param->SetValueAsDouble(GetTopElevation());
        return TransferOwnership(param);
    }
    else if(paramDefId == PARAMETER_ID(BottomElevationBuiltInParameter))
    {
        //param = NEW_AS_OWNER_PTR(Parameter, GetDocument(), ParameterStorageType::Double, false, false,
            //true, PARAMETER_UID(BottomElevationBuiltInParameter), ParameterProcessType::GeneralOutput);
        param = IParameter::CreateParameter(GetDocument(), ParameterStorageType::Double, pa,
            PARAMETER_UID(BottomElevationBuiltInParameter), ParameterProcessType::GeneralOutput);
        param->SetValueAsDouble(GetBottomElevation());
        return TransferOwnership(param);
    }
    else if(paramDefId == PARAMETER_ID(FloorSlopeAngleBuiltInParameter))
    {
        //param = NEW_AS_OWNER_PTR(Parameter, GetDocument(), ParameterStorageType::Double, false, false,
            //true, PARAMETER_UID(FloorSlopeAngleBuiltInParameter), ParameterProcessType::GeneralOutput);
        param = IParameter::CreateParameter(GetDocument(), ParameterStorageType::Double, pa,
            PARAMETER_UID(FloorSlopeAngleBuiltInParameter), ParameterProcessType::GeneralOutput);
        param->SetValueAsDouble(GetSlopeAngle());
        return TransferOwnership(param);
    }
    else if(paramDefId == PARAMETER_ID(FloorSlopeStartHeightBuiltInParameter))
    {
        //param = NEW_AS_OWNER_PTR(Parameter, GetDocument(), ParameterStorageType::Double, false, false,
            //true, PARAMETER_UID(FloorSlopeStartHeightBuiltInParameter), ParameterProcessType::GeneralOutput);
        param = IParameter::CreateParameter(GetDocument(), ParameterStorageType::Double, pa,
            PARAMETER_UID(FloorSlopeStartHeightBuiltInParameter), ParameterProcessType::GeneralOutput);
        param->SetValueAsDouble(GetSlopeStartHeight());
        return TransferOwnership(param);
    }
    else if(paramDefId == PARAMETER_ID(FloorSlopeEndHeightBuiltInParameter))
    {
        //param = NEW_AS_OWNER_PTR(Parameter, GetDocument(), ParameterStorageType::Double, false, false,
            //true, PARAMETER_UID(FloorSlopeEndHeightBuiltInParameter), ParameterProcessType::GeneralOutput);
        param = IParameter::CreateParameter(GetDocument(), ParameterStorageType::Double, pa,
            PARAMETER_UID(FloorSlopeEndHeightBuiltInParameter), ParameterProcessType::GeneralOutput);
        param->SetValueAsDouble(GetSlopeEndHeight());
        return TransferOwnership(param);
    }
    else if(paramDefId == PARAMETER_ID(ConcreteStrengthGradeBuiltInParameter))
    {
        //param = NEW_AS_OWNER_PTR(Parameter, GetDocument(), ParameterStorageType::Int, false, false,
            //true, PARAMETER_UID(ConcreteStrengthGradeBuiltInParameter), ParameterProcessType::GeneralInput);
        param = IParameter::CreateParameter(GetDocument(), ParameterStorageType::Int, pa,
            PARAMETER_UID(ConcreteStrengthGradeBuiltInParameter), ParameterProcessType::GeneralInput);
        param->SetValueAsInt((int)GetConcreteStrengthGrade__());
        return TransferOwnership(param);
    }
    return nullptr;
}

bool StructureFloor::SetNativeParameter(const IParameter *param, std::wstring* errorMsg/* = nullptr*/)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(param, L"param is null.",L"GDMPLab",L"2024-03-30");

    if(param->GetParameterDefinitionId() == PARAMETER_ID(VolumeBuiltInParameter))
    {
        SetVolume(param->GetValueAsDouble());
        return true;
    }
    else if(param->GetParameterDefinitionId() == PARAMETER_ID(AreaBuiltInParameter))
    {
        SetArea(param->GetValueAsDouble());
        return true;
    }
    else if(param->GetParameterDefinitionId() == PARAMETER_ID(TopElevationBuiltInParameter))
    {
        SetTopElevation(param->GetValueAsDouble());
        return true;
    }
    else if(param->GetParameterDefinitionId() == PARAMETER_ID(BottomElevationBuiltInParameter))
    {
        SetBottomElevation(param->GetValueAsDouble());
        return true;
    }
    else if(param->GetParameterDefinitionId() == PARAMETER_ID(FloorSlopeAngleBuiltInParameter))
    {
        SetSlopeAngle(param->GetValueAsDouble());
        return true;
    }
    else if(param->GetParameterDefinitionId() == PARAMETER_ID(FloorSlopeStartHeightBuiltInParameter))
    {
        SetSlopeStartHeight(param->GetValueAsDouble());
        return true;
    }
    else if(param->GetParameterDefinitionId() == PARAMETER_ID(FloorSlopeEndHeightBuiltInParameter))
    {
        SetSlopeEndHeight(param->GetValueAsDouble());
        return true;
    }
    else if(param->GetParameterDefinitionId() == PARAMETER_ID(ConcreteStrengthGradeBuiltInParameter))
    {
        SetConcreteStrengthGrade((ConcreteStrengthGradeType)param->GetValueAsInt());
        return true;
    }
    return false;
}

bool StructureFloor::IsParameterModifiable(int paramDefId) const
{
    if(paramDefId == PARAMETER_ID(VolumeBuiltInParameter) ||
        paramDefId == PARAMETER_ID(AreaBuiltInParameter) ||
        paramDefId == PARAMETER_ID(TopElevationBuiltInParameter) ||
        paramDefId == PARAMETER_ID(BottomElevationBuiltInParameter) ||
        paramDefId == PARAMETER_ID(FloorSlopeAngleBuiltInParameter) ||
        paramDefId == PARAMETER_ID(FloorSlopeStartHeightBuiltInParameter) ||
        paramDefId == PARAMETER_ID(FloorSlopeEndHeightBuiltInParameter))
    {
        return false;
    }
    return true;
}

void StructureFloor::Report(const ICopyContext & copyContext, ICopyStrategyReporter& reporter) const
{
    reporter.ReportToCopy(GetOwnerElementId());

    reporter.ReportToCopy(GetSlopeLineId__());
    FOR_EACH(id, GetProfileIds__())
    {
        reporter.ReportToCopy(id);
    }
}

IDocument* StructureFloor::GetDocument() const
{
    return m_pOwnerElement ? m_pOwnerElement->GetDocument() : nullptr;
}

ElementId StructureFloor::GetOwnerElementId() const
{
    return m_pOwnerElement ? m_pOwnerElement->GetElementId() : ElementId::InvalidID;
}

NdbObject* StructureFloor::GetTopOwnerObject() const
{
    if(!GetDocument())
        return nullptr;

    return quick_cast<NdbObject>(GetDocument()->GetElement(GetOwnerElementId()));
}

bool StructureFloor::Transform(const Matrix4d& matrix)
{
    // 测试代码
    Matrix4d matMirrorLocal;
    matMirrorLocal.MakeMirror(Vector3d::Zero, Vector3d::UnitY);

    IDocument* pDoc = GetDocument();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc != nullptr, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    auto profileIds = GetProfileIds();
    FOR_EACH(id, profileIds)
    {
        IElement* pProfileLineElement = pDoc->GetElement(id);
        if(pProfileLineElement)
        {
            if(!pProfileLineElement->GetElementPosition()->Transform(matMirrorLocal))
                return false;
        }
    }

    IElement* pScopeLineElement = pDoc->GetElement(GetSlopeLineId__());
    if(pScopeLineElement)
    {
        if(!pScopeLineElement->GetElementPosition()->Transform(matMirrorLocal))
            return false;
    }

    return true;
}

gcmp::StructureFloor* StructureFloor::RegisterExternalData(IInstance* pInstance)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInstance, L"pInstance为空",L"GDMPLab",L"2024-03-30");

    OwnerPtr<StructureFloor> opFloor = NEW_AS_OWNER_PTR(StructureFloor);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opFloor, L"opFloor为空",L"GDMPLab",L"2024-03-30");
    opFloor->SetOwnerElement(pInstance);

    StructureFloor* pFloor = opFloor.get();
    if (IExternalDataComponent * pExternalDataComponent = pInstance->GetExternalDataComponent())
    {
        pExternalDataComponent->RegisterExternalData(StructureFloor::GetStaticClassSchema()->GetName(), TransferOwnership(opFloor));
    }
    return pFloor;
}

OwnerPtr<IPolygon> gcmp::StructureFloor::GetProfilePolygon() const
{
    IDocument* pDoc = GetDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    std::vector<ElementId> profileIds = GetProfileIds();
    std::vector<IModelLine*> profileCurves;
    bool bOk = ProfileUsedModelLineUtils::GetModelLinesUsedForProfileByElementIds(pDoc, profileIds, profileCurves);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"获取ModelLinesUsedForProfile失败",L"GDMPLab",L"2024-03-30");

    OwnerPtr<IPolygon> opPolygon;
    Coordinate3d polygonCoord(Vector3d(0, 0, 0), Vector3d::UnitX, Vector3d::UnitY);
    bOk = StructureProfileInstanceUtils::GeneratePolygonFromProfileCurves(profileCurves, opPolygon, polygonCoord);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"Polygon生成失败",L"GDMPLab",L"2024-03-30");

    // 将轮廓线从局部坐标系转换回世界坐标系
    const IElementPosition *pElementPosition = m_pOwnerElement->GetElementPosition();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pElementPosition, L"pElementPosition为空",L"GDMPLab",L"2024-03-30");
    Matrix4d mat = pElementPosition->ComputeLocalToWorldCoordinateSystemTransformMatrix();
    opPolygon->Transform(mat);

    return opPolygon;
}

OwnerPtr<ILine3d> gcmp::StructureFloor::GetSlopeLine() const
{
    ElementId slopeLineId = GetSlopeLineId();
    if(!slopeLineId.IsValid())
    {
        return nullptr;
    }

    IElement* pSlopeElement = GetDocument()->GetElement(slopeLineId);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pSlopeElement, L"pSlopeElement为空",L"GDMPLab",L"2024-03-30");

    IGenericElement *pGenericElement = quick_cast<IGenericElement>(pSlopeElement);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pGenericElement, L"pGenericElement为空",L"GDMPLab",L"2024-03-30");

    IStructureSlopeLine* pSlopeLine = quick_cast<IStructureSlopeLine>(pGenericElement->GetExternalObject());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pSlopeLine, L"pSlopeLine为空",L"GDMPLab",L"2024-03-30");

    OwnerPtr<ILine3d> opSlopeLine = pSlopeLine->GetSlopeLine();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opSlopeLine, L"opSlopeLine为空",L"GDMPLab",L"2024-03-30");

    // 将坡度线从局部坐标系转换回世界坐标系
    const IElementPosition *pElementPosition = m_pOwnerElement->GetElementPosition();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pElementPosition, L"pElementPosition为空",L"GDMPLab",L"2024-03-30");
    Matrix4d mat = pElementPosition->ComputeLocalToWorldCoordinateSystemTransformMatrix();
    opSlopeLine->Transform(mat);

    return opSlopeLine;
}

OwnerPtr<ILine3d> gcmp::StructureFloor::GetRotationAxis() const
{
    OwnerPtr<ILine3d> opSlopeLine = GetSlopeLine();
    if(!opSlopeLine)
    {
        return nullptr;
    }

    Vector3d rotationAxisDirection = opSlopeLine->GetDirection().Cross(Vector3d::UnitZ);
    rotationAxisDirection.Normalize();
    Vector3d startPt = opSlopeLine->GetStartPoint();
    OwnerPtr<ILine3d> opRotationAxis = ILine3d::Create(startPt, rotationAxisDirection, Intervald(0.0, 1000.0));
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opRotationAxis, L"opRotationAxis为空",L"GDMPLab",L"2024-03-30");

    return opRotationAxis;
}

bool gcmp::StructureFloor::UpdateFloorProfilesAndSlopeLine(const std::vector<IModelLine*> profileCurves, const IStructureSlopeLine* pSlopeLine)
{
    std::vector<ElementId> profileIds;
    FOR_EACH(pModelLine, profileCurves)
    {
        profileIds.push_back(pModelLine->GetOwnerElement()->GetElementId());
    }
    this->SetProfileIds(profileIds);

    if(!pSlopeLine)
    {
        this->SetSlopeLineId(ElementId::InvalidID);
    }
    else if(pSlopeLine->GetOwnerElement() && pSlopeLine->GetOwnerElement()->GetElementId() != ElementId::InvalidID)
    {
        this->SetSlopeLineId(pSlopeLine->GetOwnerElement()->GetElementId());
    }
    return true;
}